package com.ytjj.common.utils;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSSClient;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.geoip.model.v20200101.DescribeIpv4LocationRequest;
import com.aliyuncs.geoip.model.v20200101.DescribeIpv4LocationResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;
import com.ytjj.common.constants.OSSClientConstants;
import com.ytjj.common.exception.ApiException;
import com.ytjj.common.model.FileResponse;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;

/**
 *
 * @version 1.0
 * @description 阿里云 oss 对象存储 工具类
 **/
@Component
@Slf4j
public class AliyunOSSClientUtil {

    //oss参数实体类
    private static OSSClientConstants ossEntity;

    public OSSClientConstants getOssEntity() {
        return ossEntity;
    }

    public void setOssEntity(OSSClientConstants ossEntity) {
        this.ossEntity = ossEntity;
    }
    /**
     * 获取阿里云OSS客户端对象 (初始化)
     *
     * @return ossClient
     */
    public static OSSClient getOSSClient() {
        return new OSSClient(ossEntity.getEndPoint(), ossEntity.getAccessKeyId(), ossEntity.getAccessKeySecret());
    }



    /**
     * 根据key删除OSS服务器上的文件
     *
     * @param ossClient  oss连接
     * @param bucketName 存储空间
     * @param folder     模拟文件夹名 如"qj_nanjing/"
     * @param key        Bucket下的文件的路径名+文件名 如："default/123.jpg"
     */
    public static void deleteFile(OSSClient ossClient, String bucketName, String folder, String key) {
        ossClient.deleteObject(bucketName, folder + key);
        log.info("删除" + bucketName + "下的文件" + folder + key + "成功");
    }


    /**
     * 上传图片至OSS
     *
     * @param ossClient oss连接
     * @param file      MultipartFile 文件
     * @param folder    指定上传文件夹路径
     * @return FileDto   上传结果
     */
    public static FileResponse uploadObject2OSS(OSSClient ossClient, MultipartFile file, String folder) {
        return uploadObject2OSS(ossClient, file, ossEntity.getBacketName(), folder);
    }

    /**
     * 图片压缩至OSS
     *
     * @param ossClient oss连接
     * @param file      MultipartFile 文件
     * @param folder    指定上传文件夹路径
     * @return FileDto   上传结果
     */
    public static FileResponse uploadCompressImgToOSS(OSSClient ossClient, MultipartFile file, String folder) {
        return uploadCompressImgToOSS(ossClient, file, ossEntity.getBacketName(), folder);
    }

    /**
     * 上传图片至OSS
     *
     * @param ossClient oss连接
     * @param file      MultipartFile 文件
     * @return FileDto   上传结果
     */
    public static FileResponse uploadObject2OSS(OSSClient ossClient, MultipartFile file) {
        return uploadObject2OSS(ossClient, file, ossEntity.getBacketName(), ossEntity.getFolder());
    }
    /**
     * 上传图片至OSS
     *
     * @param ossClient oss连接
     * @param file      MultipartFile 文件
     * @return FileDto   上传结果
     */
    public static FileResponse uploadObject2OSS(OSSClient ossClient, InputStream file,String suffix) {
        return uploadObject2OSS(ossClient, file, ossEntity.getBacketName(), ossEntity.getFolder(),suffix);
    }

    /**
     * 上传图片至OSS
     *
     * @param ossClient  oss连接
     * @param file       MultipartFile 文件
     * @param bucketName 存储空间
     * @param folder     文件夹名称
     * @return FileDto   上传结果
     */
    public static FileResponse uploadObject2OSS(OSSClient ossClient, MultipartFile file, String bucketName, String folder) {
        log.info("  上传参数bucketName , folder ===> " + bucketName + " , " + folder);

        FileResponse dto = new FileResponse();
        try {
            StringBuilder fileUrl = new StringBuilder();
            String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf('.'));
            String point = ".";
            String uuid = UUID.randomUUID().toString().replaceAll("-","");
            dto.setSize(file.getSize());
            dto.setId(uuid);
            dto.setName(file.getOriginalFilename());

            if (!suffix.startsWith(point)) {
                suffix = point + suffix;
            }
            String fileName = uuid + suffix;
            if (!folder.endsWith("/")) {
                folder = folder.concat("/");
            }
            fileUrl.append(folder).append(fileName);
            ossClient.putObject(bucketName, fileUrl.toString(), file.getInputStream());
            // 文件url
            dto.setUrl(getFileUrl(fileName, folder));
            log.info("文件上传成功 ===>" + dto.getName());
            return dto;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 上传图片到oss
     * @param suffix 图片后缀格式
     */
    public static String uploadImgToOSS(OSSClient ossClient, InputStream inputStream, String suffix) {
        log.info("上传文件后缀 ===> " + suffix);
        String folder = "other";
        try {
            StringBuilder fileUrl = new StringBuilder();
            String point = ".";
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            if (!suffix.startsWith(point)) {
                suffix = point + suffix;
            }
            String fileName = uuid + suffix;
            if (!folder.endsWith("/")) {
                folder = folder.concat("/");
            }
            fileUrl.append(folder).append(fileName);
            ossClient.putObject(ossEntity.getBacketName(), fileUrl.toString(), inputStream);
            String url = getFileUrl(fileName, folder);
            // 文件url
            log.info("文件上传成功 ===>" + url);
            return url;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }



    /**
     * 上传压缩图
     */
    public static FileResponse uploadCompressImgToOSS(OSSClient ossClient, MultipartFile file, String bucketName, String folder) {
        log.info("  上传参数bucketName , folder ===> " + bucketName + " , " + folder);
        FileResponse dto = new FileResponse();
        try {
            String point = ".";
            String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf('.'));
            if (!suffix.startsWith(point)) {
                suffix = point + suffix;
            }
            //获取图片的后缀格式
            String fileExtension =  suffix.substring(suffix.lastIndexOf('.') + 1).toLowerCase(Locale.ROOT);
            log.info("文件格式是====》"+fileExtension);
            //如果是webp格式不处理
            if(fileExtension.equalsIgnoreCase("webp")){
                return uploadObject2OSS(ossClient, file, bucketName, folder);
            }
            InputStream input = file.getInputStream();
            // 把图片读入到内存中
            BufferedImage bi = ImageIO.read(input);
            //如果是jpg或者是jpeg，需要重画一下，否则会变色
            if (fileExtension.equalsIgnoreCase("jpg") || fileExtension.equalsIgnoreCase("jpeg")) {
                BufferedImage tag = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_BGR);
                Graphics g = tag.getGraphics();
                // 绘制缩小后的图
                g.drawImage(bi, 0, 0, null);
                g.dispose();
                bi = tag;
            }
            // 压缩代码
            BufferedImage bufImg = Thumbnails.of(bi).width(1024).keepAspectRatio(true).outputQuality(0.2).asBufferedImage();
            // 存储图片文件byte数组
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(bufImg,fileExtension, bos);
            //以输入流的形式上传文件
            InputStream is = new ByteArrayInputStream(bos.toByteArray());
            String uuid = UUID.randomUUID().toString().replaceAll("-","");
            byte[] bytes = bos.toByteArray();
            dto.setSize(Long.valueOf(bytes.length));
            dto.setId(uuid);
            dto.setName(file.getOriginalFilename());
            String fileName = uuid + suffix;
            if (!folder.endsWith("/")) {
                folder = folder.concat("/");
            }
            StringBuilder fileUrl = new StringBuilder();
            fileUrl.append(folder).append(fileName);
            ossClient.putObject(bucketName, fileUrl.toString(), is);
            // 文件url
            dto.setUrl(getFileUrl(fileName, folder));
            log.info("压缩图片上传成功 ===>" + dto.getName());
            return dto;
        } catch (Exception e) {
            log.error("压缩图片上传出错！",e);
            return null;
        }
    }

    /**
     * 上传图片至OSS
     *
     * @param ossClient  oss连接
     * @param inputStream       MultipartFile 文件
     * @param bucketName 存储空间
     * @param folder     文件夹名称
     * @return FileDto   上传结果
     */
    public static FileResponse uploadObject2OSS(OSSClient ossClient, InputStream inputStream, String bucketName, String folder ,String suffix) {
        log.info("  上传参数bucketName , folder ===> " + bucketName + " , " + folder);

        FileResponse dto = new FileResponse();
        try {
            StringBuilder fileUrl = new StringBuilder();
            String point = ".";
            String uuid = UUID.randomUUID().toString().replaceAll("-","");
//            dto.setSize(file.getSize());
            dto.setId(uuid);
//            dto.setName(file.getOriginalFilename());

            if (!suffix.startsWith(point)) {
                suffix = point + suffix;
            }
            String fileName = uuid + suffix;
            if (!folder.endsWith("/")) {
                folder = folder.concat("/");
            }
            fileUrl.append(folder).append(fileName);
            ossClient.putObject(bucketName, fileUrl.toString(), inputStream);
            // 文件url
            dto.setUrl(getFileUrl(fileName, folder));
            log.info("文件上传成功 ===>" + dto.getName());
            return dto;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }



    public static String wmTextUpload(MultipartFile file,String sn){
        if(file==null|| StrUtil.isEmpty(sn)){
            throw  new ApiException("传入参数不能为空");
        }
        String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf('.'));
        try (InputStream inputStream=file.getInputStream();
             ByteArrayOutputStream os = new ByteArrayOutputStream();){

            //获取图片名称
            String fileName= file.getOriginalFilename();
            Image srcImg= ImageIO.read(inputStream);
            LocalDateTime now = LocalDateTime.now();
            // add by chenxin  start   给图片加上水印
            Font font = new Font("微软雅黑", Font.PLAIN, 30);                     //水印字体
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            String waterMarkContent = sn; //水印内容
            Color color = new Color(255, 255, 100, 50);
            if(srcImg!=null){
                int srcImgWidth = srcImg.getWidth(null);//获取图片的宽
                int srcImgHeight = srcImg.getHeight(null);//获取图片的高
                // 加水印
                BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
                Graphics2D g = bufImg.createGraphics();
                g.drawImage(srcImg, 1, 2, srcImgWidth, srcImgHeight, null);

                g.setColor(color); //根据图片的背景设置水印颜色
                g.setFont(font);              //设置字体
                g.drawString(waterMarkContent, 100, 100);  //画出水印
                g.dispose();
                System.out.println("文件名称为："+file.getOriginalFilename());
                ImageIO.write(bufImg, "jpg", os);
                bufImg.flush();
                try (InputStream input = new ByteArrayInputStream(os.toByteArray())){
                    OSSClient ossClient = AliyunOSSClientUtil.getOSSClient();
                    log.info("开始上传文件 =====>" + file.getOriginalFilename());
                    FileResponse fileResponse = AliyunOSSClientUtil.uploadObject2OSS(ossClient, input,suffix);
                    //          String url = AliOssUtils.uploadFileToOssFileName(file,"device");
//                    String url = uploadObject2OSS(input, "device/"+sn, 1, fileName);

                    return  fileResponse.getUrl();
                }
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }//文件转化为图片
        catch (Exception e){
            log.info("上传图片失败{}",e.getMessage());
        }
        return null;

    }


    public static String wmImgUpload(MultipartFile goalFile, MultipartFile wmFile){
        //goalFile-上传文件 wmFile-水印文件
        if (goalFile == null || wmFile== null) {
            throw new ApiException("上传文件/水印文件不能为空!");
        }

        String suffix = Objects.requireNonNull(goalFile.getOriginalFilename()).substring(goalFile.getOriginalFilename().lastIndexOf('.'));
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try{
            //上传文件操作
            InputStream inputStream01 = goalFile.getInputStream();
            Image srcImg = ImageIO.read(inputStream01);
            BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null), srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics = buffImg.createGraphics();
            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            graphics.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null),
                    srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0, null);
            //水印文件操作
            InputStream inputStream02 = wmFile.getInputStream();
            ImageIcon logoImgIcon = new ImageIcon(ImageIO.read(inputStream02));
            Image logoImg = logoImgIcon.getImage();

            //旋转
            double degree = 1;
            if (degree > 0) {
                graphics.rotate(Math.toRadians(degree),
                        (double) buffImg.getWidth() / 2,
                        (double) buffImg.getWidth() / 2);
            }

            float alpha = 1f; // 透明度
            graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

            //水印 的位置
            graphics.drawImage(logoImg, buffImg.getWidth()/3, buffImg.getHeight()/2, null);
            graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
            graphics.dispose();

            // 生成图片
            ImageIO.write(buffImg, "jpg", os);

            InputStream input = new ByteArrayInputStream(os.toByteArray());
            OSSClient ossClient = AliyunOSSClientUtil.getOSSClient();
            log.info("开始上传文件 =======> " + goalFile.getOriginalFilename());
            FileResponse fileResponse = AliyunOSSClientUtil.uploadObject2OSS(ossClient, input, suffix);

            return fileResponse.getUrl();

        } catch (IOException e){
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        }
        return "文件上传失败!";
    }


    /**
     * 拼接文件url
     *
     * @param fileName 文件名称
     * @return url
     */
    public static String getFileUrl(String fileName, String FOLDER) {
         return "https://" + ossEntity.getEndPoint() + "/" + FOLDER +/* "/" + */fileName;
        //return "http://" + ENDPOINT + "/" + folder + fileName;
    }

    /**
     * @Description: 获取视频截图
     * @throws IOException  void
     */
    public static Map<String, Object> getScreenshot(String filePath){
        Map<String, Object> result = new HashMap<>();
        try {
            FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(filePath);

            // 第一帧图片存储位置
            // String targerFilePath = filePath.substring(0, filePath.lastIndexOf("\\"));
            // 视频文件名
            // String fileName = filePath.substring(filePath.lastIndexOf("\\") + 1);
            // 图片名称
            // String targetFileName = fileName.substring(0, fileName.lastIndexOf("."));

            grabber.start();
            //设置视频截取帧（默认取第一帧）
            Frame frame = grabber.grabImage();
            Java2DFrameConverter converter = new Java2DFrameConverter();
            //绘制图片
            BufferedImage bi = converter.getBufferedImage(frame);
            //图片的类型
            // String imageMat = "jpg";
            //图片的完整路径
            // String imagePath = targerFilePath + File.separator + targetFileName + "." + imageMat;
            //创建文件
            // File output = new File(imagePath);
            // ImageIO.write(bi, imageMat, output);

            //拼接Map信息
            result.put("videoWide", bi.getWidth());
            result.put("videoHigh", bi.getHeight());
            result.put("format", grabber.getFormat());
            // result.put("imgPath", output.getPath());
            grabber.stop();
        } catch (Exception e) {
            log.info("解析的url视频信息报错！");
            e.printStackTrace();
            result = null;
        }
        log.info("解析的url视频信息为："+ JSON.toJSONString(result));
        return result;

    }


    public static String getAddressByIp(String ip){
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", ossEntity.getAccessKeyId(), ossEntity.getAccessKeySecret());
        IAcsClient client = new DefaultAcsClient(profile);

        DescribeIpv4LocationRequest request = new DescribeIpv4LocationRequest();
        request.setIp(ip);
        try {
            DescribeIpv4LocationResponse response = client.getAcsResponse(request);
            String address = new Gson().toJson(response);
//            log.info("该IP{"+ip+"}的地理位置为：",address);
            return address;
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.error("ErrCode:" + e.getErrCode());
            log.error("ErrMsg:" + e.getErrMsg());
            log.error("RequestId:" + e.getRequestId());
        }
        return null;
    }

    public static void main(String[] args) {
        Map<String,Object> result = getScreenshot("D:\\vedio\\3452352.mp4");
    }

}
